#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
智能问题类型识别器

根据优化方案实现的问题理解能力提升模块：
1. 自动识别问题类型
2. 业务场景理解
3. 推荐分析方法
4. 提取决策上下文
"""

import re
import numpy as np
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
import jieba
from collections import Counter
import logging


class ProblemType(Enum):
    """问题类型枚举"""
    MULTI_SCENARIO = "multi_scenario"  # 多情形决策
    SINGLE_OBJECTIVE = "single_objective"  # 单目标优化
    MULTI_OBJECTIVE = "multi_objective"  # 多目标优化
    UNCERTAINTY = "uncertainty"  # 不确定性决策
    DYNAMIC = "dynamic"  # 动态决策
    RESOURCE_ALLOCATION = "resource_allocation"  # 资源分配
    SCHEDULING = "scheduling"  # 调度问题
    PORTFOLIO = "portfolio"  # 投资组合
    QUALITY_CONTROL = "quality_control"  # 质量控制
    SUPPLY_CHAIN = "supply_chain"  # 供应链优化


class BusinessDomain(Enum):
    """业务领域枚举"""
    MANUFACTURING = "manufacturing"  # 制造业
    FINANCE = "finance"  # 金融
    LOGISTICS = "logistics"  # 物流
    HEALTHCARE = "healthcare"  # 医疗
    ENERGY = "energy"  # 能源
    RETAIL = "retail"  # 零售
    TECHNOLOGY = "technology"  # 科技
    GENERAL = "general"  # 通用


@dataclass
class ProblemClassification:
    """问题分类结果"""
    primary_type: ProblemType
    secondary_types: List[ProblemType]
    business_domain: BusinessDomain
    confidence_scores: Dict[str, float]
    keywords_found: List[str]
    recommended_approach: Dict[str, Any]
    context_info: Dict[str, Any]


class ProblemTypeClassifier:
    """
    智能问题类型识别器
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
        # 问题类型关键词模式
        self.problem_patterns = {
            ProblemType.MULTI_SCENARIO: {
                'keywords': ['情形', '情况', '场景', 'scenario', '情景', '案例', '条件下', '不同', '各种'],
                'patterns': [r'情形\d+', r'场景\d+', r'情况\d+', r'\d+种情形', r'\d+个场景'],
                'weight': 1.0
            },
            ProblemType.SINGLE_OBJECTIVE: {
                'keywords': ['最大化', '最小化', 'maximize', 'minimize', '最优', '最佳', '极值'],
                'patterns': [r'最大化.*利润', r'最小化.*成本', r'最优.*决策'],
                'weight': 0.8
            },
            ProblemType.MULTI_OBJECTIVE: {
                'keywords': ['多目标', '权衡', 'pareto', '帕累托', '平衡', '兼顾', '同时'],
                'patterns': [r'既要.*又要', r'同时.*和.*', r'平衡.*与.*'],
                'weight': 1.0
            },
            ProblemType.UNCERTAINTY: {
                'keywords': ['不确定', '随机', '概率', 'uncertainty', '风险', '波动', '变化'],
                'patterns': [r'不确定.*条件', r'随机.*变量', r'概率.*分布'],
                'weight': 0.9
            },
            ProblemType.DYNAMIC: {
                'keywords': ['动态', '时间', '阶段', 'dynamic', '时序', '周期', '阶段性'],
                'patterns': [r'动态.*调整', r'时间.*序列', r'阶段.*决策'],
                'weight': 0.9
            },
            ProblemType.QUALITY_CONTROL: {
                'keywords': ['质量', '检测', '拆解', '次品', '合格', '质控', '检验', '品质'],
                'patterns': [r'质量.*控制', r'检测.*方案', r'次品.*处理'],
                'weight': 1.0
            },
            ProblemType.RESOURCE_ALLOCATION: {
                'keywords': ['资源', '分配', '配置', '调配', '分布', '资源配置'],
                'patterns': [r'资源.*分配', r'配置.*方案', r'调配.*策略'],
                'weight': 0.9
            },
            ProblemType.SUPPLY_CHAIN: {
                'keywords': ['供应链', '库存', '运输', '供应商', '物流', '配送'],
                'patterns': [r'供应链.*优化', r'库存.*管理', r'运输.*方案'],
                'weight': 0.9
            }
        }
        
        # 业务领域关键词
        self.domain_patterns = {
            BusinessDomain.MANUFACTURING: {
                'keywords': ['生产', '制造', '工厂', '产品', '零配件', '组装', '加工'],
                'weight': 1.0
            },
            BusinessDomain.FINANCE: {
                'keywords': ['投资', '金融', '股票', '债券', '风险', '收益', '资产'],
                'weight': 1.0
            },
            BusinessDomain.LOGISTICS: {
                'keywords': ['物流', '运输', '配送', '仓储', '路径', '调度'],
                'weight': 1.0
            },
            BusinessDomain.HEALTHCARE: {
                'keywords': ['医疗', '健康', '医院', '患者', '治疗', '药物'],
                'weight': 1.0
            },
            BusinessDomain.ENERGY: {
                'keywords': ['能源', '电力', '发电', '节能', '电网', '燃料'],
                'weight': 1.0
            },
            BusinessDomain.RETAIL: {
                'keywords': ['零售', '销售', '商品', '顾客', '门店', '促销'],
                'weight': 1.0
            }
        }
        
        # 方法推荐模板
        self.methodology_templates = {
            ProblemType.MULTI_SCENARIO: {
                'approach': 'scenario_analysis',
                'algorithms': ['exhaustive_search', 'scenario_optimization', 'decision_tree'],
                'output_format': 'scenario_comparison_table',
                'analysis_focus': ['scenario_comparison', 'sensitivity_analysis', 'robustness'],
                'visualization': ['scenario_heatmap', 'decision_tree', 'comparison_chart']
            },
            ProblemType.SINGLE_OBJECTIVE: {
                'approach': 'single_optimization',
                'algorithms': ['linear_programming', 'genetic_algorithm', 'simulated_annealing'],
                'output_format': 'optimal_solution',
                'analysis_focus': ['optimality', 'sensitivity', 'convergence'],
                'visualization': ['convergence_plot', 'solution_space', 'sensitivity_chart']
            },
            ProblemType.MULTI_OBJECTIVE: {
                'approach': 'pareto_optimization',
                'algorithms': ['nsga2', 'spea2', 'moea_d'],
                'output_format': 'pareto_frontier',
                'analysis_focus': ['pareto_frontier', 'trade_offs', 'solution_diversity'],
                'visualization': ['pareto_plot', 'trade_off_chart', 'solution_scatter']
            },
            ProblemType.UNCERTAINTY: {
                'approach': 'stochastic_optimization',
                'algorithms': ['monte_carlo', 'robust_optimization', 'chance_constrained'],
                'output_format': 'robust_solution',
                'analysis_focus': ['risk_analysis', 'robustness', 'confidence_intervals'],
                'visualization': ['risk_profile', 'confidence_bands', 'scenario_tree']
            },
            ProblemType.QUALITY_CONTROL: {
                'approach': 'quality_optimization',
                'algorithms': ['decision_analysis', 'cost_benefit_optimization', 'reliability_optimization'],
                'output_format': 'quality_strategy',
                'analysis_focus': ['cost_benefit', 'quality_metrics', 'process_optimization'],
                'visualization': ['quality_dashboard', 'cost_benefit_chart', 'process_flow']
            }
        }
    
    def classify_problem(self, problem_description: str) -> ProblemClassification:
        """
        自动识别问题类型
        
        Args:
            problem_description: 问题描述文本
            
        Returns:
            ProblemClassification: 分类结果
        """
        # 文本预处理
        text = self._preprocess_text(problem_description)
        
        # 计算各问题类型的匹配度
        type_scores = self._calculate_type_scores(text)
        
        # 计算业务领域匹配度
        domain_scores = self._calculate_domain_scores(text)
        
        # 提取关键词
        keywords_found = self._extract_keywords(text)
        
        # 确定主要类型和次要类型
        sorted_types = sorted(type_scores.items(), key=lambda x: x[1], reverse=True)
        primary_type = sorted_types[0][0] if sorted_types else ProblemType.SINGLE_OBJECTIVE
        secondary_types = [t for t, s in sorted_types[1:3] if s > 0.3]
        
        # 确定业务领域
        business_domain = max(domain_scores.items(), key=lambda x: x[1])[0] if domain_scores else BusinessDomain.GENERAL
        
        # 获取推荐方法
        recommended_approach = self._get_recommended_approach(primary_type, secondary_types)
        
        # 提取上下文信息
        context_info = self._extract_context_info(text, primary_type)
        
        return ProblemClassification(
            primary_type=primary_type,
            secondary_types=secondary_types,
            business_domain=business_domain,
            confidence_scores={
                'type_scores': type_scores,
                'domain_scores': domain_scores
            },
            keywords_found=keywords_found,
            recommended_approach=recommended_approach,
            context_info=context_info
        )
    
    def _preprocess_text(self, text: str) -> str:
        """
        文本预处理
        """
        # 转换为小写
        text = text.lower()
        
        # 移除特殊字符但保留中文
        text = re.sub(r'[^\w\s\u4e00-\u9fff]', ' ', text)
        
        # 移除多余空格
        text = re.sub(r'\s+', ' ', text).strip()
        
        return text
    
    def _calculate_type_scores(self, text: str) -> Dict[ProblemType, float]:
        """
        计算问题类型匹配度
        """
        scores = {}
        
        for problem_type, config in self.problem_patterns.items():
            score = 0.0
            
            # 关键词匹配
            keyword_matches = sum(1 for keyword in config['keywords'] if keyword in text)
            keyword_score = keyword_matches / len(config['keywords'])
            
            # 模式匹配
            pattern_matches = sum(1 for pattern in config['patterns'] if re.search(pattern, text))
            pattern_score = pattern_matches / len(config['patterns']) if config['patterns'] else 0
            
            # 综合得分
            score = (keyword_score * 0.7 + pattern_score * 0.3) * config['weight']
            scores[problem_type] = score
        
        return scores
    
    def _calculate_domain_scores(self, text: str) -> Dict[BusinessDomain, float]:
        """
        计算业务领域匹配度
        """
        scores = {}
        
        for domain, config in self.domain_patterns.items():
            keyword_matches = sum(1 for keyword in config['keywords'] if keyword in text)
            score = (keyword_matches / len(config['keywords'])) * config['weight']
            scores[domain] = score
        
        return scores
    
    def _extract_keywords(self, text: str) -> List[str]:
        """
        提取关键词
        """
        keywords = []
        
        # 从所有模式中提取匹配的关键词
        for config in self.problem_patterns.values():
            for keyword in config['keywords']:
                if keyword in text:
                    keywords.append(keyword)
        
        for config in self.domain_patterns.values():
            for keyword in config['keywords']:
                if keyword in text:
                    keywords.append(keyword)
        
        return list(set(keywords))
    
    def _get_recommended_approach(self, primary_type: ProblemType, 
                                secondary_types: List[ProblemType]) -> Dict[str, Any]:
        """
        获取推荐的分析方法
        """
        base_approach = self.methodology_templates.get(primary_type, 
                                                     self.methodology_templates[ProblemType.SINGLE_OBJECTIVE])
        
        # 根据次要类型调整方法
        if secondary_types:
            # 合并算法选项
            additional_algorithms = []
            for sec_type in secondary_types:
                if sec_type in self.methodology_templates:
                    additional_algorithms.extend(self.methodology_templates[sec_type]['algorithms'])
            
            base_approach = base_approach.copy()
            base_approach['algorithms'] = list(set(base_approach['algorithms'] + additional_algorithms))
        
        return base_approach
    
    def _extract_context_info(self, text: str, primary_type: ProblemType) -> Dict[str, Any]:
        """
        提取决策上下文信息
        """
        context = {
            'text_length': len(text),
            'complexity_indicators': [],
            'decision_variables': [],
            'objectives': [],
            'constraints': []
        }
        
        # 提取数字信息
        numbers = re.findall(r'\d+(?:\.\d+)?', text)
        if numbers:
            context['numeric_values'] = [float(n) for n in numbers[:10]]  # 限制数量
        
        # 提取复杂度指标
        if '多' in text or '复杂' in text:
            context['complexity_indicators'].append('high_complexity')
        if '简单' in text or '基本' in text:
            context['complexity_indicators'].append('low_complexity')
        
        # 根据问题类型提取特定信息
        if primary_type == ProblemType.MULTI_SCENARIO:
            scenarios = re.findall(r'情形\d+|场景\d+|情况\d+', text)
            context['scenarios'] = scenarios
        
        elif primary_type == ProblemType.QUALITY_CONTROL:
            quality_terms = ['检测', '拆解', '次品', '合格率', '质量']
            context['quality_aspects'] = [term for term in quality_terms if term in text]
        
        return context


class BusinessScenarioAnalyzer:
    """
    业务场景深度理解分析器
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
        # 业务场景模板
        self.scenario_templates = {
            'quality_control': {
                'variables': ['检测', '拆解', '质量', '成本', '时间'],
                'objectives': ['利润', '成本', '质量', '效率'],
                'constraints': ['预算', '时间', '资源', '质量标准'],
                'key_decisions': ['是否检测', '检测方式', '处理策略'],
                'success_metrics': ['利润最大化', '成本最小化', '质量保证']
            },
            'supply_chain': {
                'variables': ['库存', '运输', '供应商', '需求'],
                'objectives': ['成本', '服务水平', '风险'],
                'constraints': ['容量', '时间', '预算', '质量'],
                'key_decisions': ['库存水平', '供应商选择', '运输方式'],
                'success_metrics': ['总成本最小', '服务水平最高', '风险最低']
            },
            'resource_allocation': {
                'variables': ['资源', '任务', '时间', '人员'],
                'objectives': ['效率', '成本', '质量'],
                'constraints': ['资源限制', '时间限制', '技能要求'],
                'key_decisions': ['资源分配', '任务排序', '人员安排'],
                'success_metrics': ['资源利用率', '任务完成率', '成本控制']
            }
        }
    
    def analyze_scenario(self, problem_description: str, 
                        problem_classification: ProblemClassification) -> Dict[str, Any]:
        """
        分析业务场景特征
        
        Args:
            problem_description: 问题描述
            problem_classification: 问题分类结果
            
        Returns:
            Dict[str, Any]: 场景分析结果
        """
        # 根据问题类型选择场景模板
        scenario_type = self._map_problem_to_scenario(problem_classification.primary_type)
        template = self.scenario_templates.get(scenario_type, {})
        
        # 提取场景要素
        scenario_elements = self._extract_scenario_elements(problem_description, template)
        
        # 分析决策复杂度
        complexity_analysis = self._analyze_complexity(problem_description, scenario_elements)
        
        # 识别关键成功因素
        success_factors = self._identify_success_factors(problem_description, template)
        
        # 风险评估
        risk_assessment = self._assess_risks(problem_description, scenario_elements)
        
        return {
            'scenario_type': scenario_type,
            'scenario_elements': scenario_elements,
            'complexity_analysis': complexity_analysis,
            'success_factors': success_factors,
            'risk_assessment': risk_assessment,
            'recommendations': self._generate_recommendations(scenario_type, complexity_analysis)
        }
    
    def _map_problem_to_scenario(self, problem_type: ProblemType) -> str:
        """
        将问题类型映射到业务场景
        """
        mapping = {
            ProblemType.QUALITY_CONTROL: 'quality_control',
            ProblemType.SUPPLY_CHAIN: 'supply_chain',
            ProblemType.RESOURCE_ALLOCATION: 'resource_allocation'
        }
        return mapping.get(problem_type, 'general')
    
    def _extract_scenario_elements(self, text: str, template: Dict) -> Dict[str, List[str]]:
        """
        提取场景要素
        """
        elements = {
            'variables': [],
            'objectives': [],
            'constraints': [],
            'decisions': []
        }
        
        for category, keywords in template.items():
            if category in elements:
                found_elements = [kw for kw in keywords if kw in text]
                elements[category] = found_elements
        
        return elements
    
    def _analyze_complexity(self, text: str, elements: Dict) -> Dict[str, Any]:
        """
        分析决策复杂度
        """
        complexity_score = 0
        factors = []
        
        # 基于要素数量评估复杂度
        total_elements = sum(len(v) for v in elements.values())
        if total_elements > 10:
            complexity_score += 3
            factors.append('多要素复杂')
        elif total_elements > 5:
            complexity_score += 2
            factors.append('中等复杂')
        else:
            complexity_score += 1
            factors.append('相对简单')
        
        # 基于文本长度评估
        if len(text) > 500:
            complexity_score += 2
            factors.append('描述详细')
        
        # 基于数字数量评估
        numbers = re.findall(r'\d+', text)
        if len(numbers) > 10:
            complexity_score += 2
            factors.append('参数众多')
        
        complexity_level = 'low' if complexity_score <= 3 else 'medium' if complexity_score <= 6 else 'high'
        
        return {
            'score': complexity_score,
            'level': complexity_level,
            'factors': factors
        }
    
    def _identify_success_factors(self, text: str, template: Dict) -> List[str]:
        """
        识别关键成功因素
        """
        success_factors = []
        
        # 从模板中获取成功指标
        template_metrics = template.get('success_metrics', [])
        for metric in template_metrics:
            if any(word in text for word in metric.split()):
                success_factors.append(metric)
        
        # 基于关键词识别
        success_keywords = {
            '效率': '提高效率',
            '成本': '控制成本',
            '质量': '保证质量',
            '利润': '增加利润',
            '风险': '降低风险'
        }
        
        for keyword, factor in success_keywords.items():
            if keyword in text:
                success_factors.append(factor)
        
        return list(set(success_factors))
    
    def _assess_risks(self, text: str, elements: Dict) -> Dict[str, Any]:
        """
        评估风险
        """
        risks = []
        risk_level = 'low'
        
        # 基于不确定性关键词
        uncertainty_keywords = ['不确定', '变化', '波动', '风险']
        uncertainty_count = sum(1 for kw in uncertainty_keywords if kw in text)
        
        if uncertainty_count > 2:
            risks.append('高不确定性')
            risk_level = 'high'
        elif uncertainty_count > 0:
            risks.append('中等不确定性')
            risk_level = 'medium'
        
        # 基于约束数量
        constraint_count = len(elements.get('constraints', []))
        if constraint_count > 3:
            risks.append('约束复杂')
        
        # 基于目标冲突
        objective_count = len(elements.get('objectives', []))
        if objective_count > 2:
            risks.append('目标冲突')
        
        return {
            'level': risk_level,
            'factors': risks,
            'mitigation_needed': len(risks) > 2
        }
    
    def _generate_recommendations(self, scenario_type: str, 
                                complexity_analysis: Dict) -> List[str]:
        """
        生成建议
        """
        recommendations = []
        
        # 基于复杂度的建议
        if complexity_analysis['level'] == 'high':
            recommendations.extend([
                '建议分阶段实施决策',
                '考虑使用高级优化算法',
                '进行敏感性分析'
            ])
        elif complexity_analysis['level'] == 'medium':
            recommendations.extend([
                '可使用标准优化方法',
                '建议进行情景分析'
            ])
        else:
            recommendations.extend([
                '可使用简单优化方法',
                '重点关注关键指标'
            ])
        
        # 基于场景类型的建议
        scenario_recommendations = {
            'quality_control': [
                '重点关注成本效益分析',
                '考虑质量风险评估',
                '建立质量监控机制'
            ],
            'supply_chain': [
                '考虑供应链弹性',
                '评估供应商风险',
                '优化库存策略'
            ],
            'resource_allocation': [
                '平衡资源利用率',
                '考虑技能匹配',
                '建立动态调整机制'
            ]
        }
        
        recommendations.extend(scenario_recommendations.get(scenario_type, []))
        
        return recommendations


def create_problem_classifier() -> ProblemTypeClassifier:
    """
    创建问题分类器实例
    """
    return ProblemTypeClassifier()


def create_scenario_analyzer() -> BusinessScenarioAnalyzer:
    """
    创建场景分析器实例
    """
    return BusinessScenarioAnalyzer()